#region Copyright Jonathan Quiros

//	
// All rights are reserved. Reproduction or transmission in whole or in 
// part, in any form or by any means, electronic, mechanical or otherwise, 
// is prohibited without the prior written consent of the copyright owner.
//
// Filename: UsersRepository.cs
//

#endregion

using System.Linq;
using System.Collections.Generic;
using Novagoal.Models;
using Novagoal.Models.Utils;
using Novagoal.Repositories.Extensions;
using Ids.Web.Listing;

namespace Novagoal.Repositories.Entities
{
    public class UsersRepository : BaseRepository, IUsersRepository
    {
        #region CONSTANTS



        #endregion

        #region PROPERTIES

        

        #endregion

        #region PUBLIC METHODS

        public Person GetPerson(string email)
        {
            return EntitiesContext.people
                .Where(p => p.email_address == email)
                .Select(CreatePerson)
                .FirstOrDefault();
        }

        public Person GetPerson(int id)
        {
            return EntitiesContext.people
                .Where(p => p.id == id)
                .Select(CreatePerson)
                .FirstOrDefault();
        }

        public User GetUser(string username)
        {
            return EntitiesContext.users.Where(u => u.people.email_address == username)
                .Select(CreateUser)
                .FirstOrDefault();
        }

        public User GetUser(int id)
        {
            return EntitiesContext.users.Where(u => u.id == id)
                .Select(CreateUser)
                .FirstOrDefault();
        }

        public List<User> GetUsers(Dictionary<UserListFilter, string> filterList, UserListSortField sortField, SortDirectionType sortDirection, int currentPage, int pageSize)
        {
            var qryUsers = FilterUsers(filterList);

            var users = SortUsers(qryUsers, sortField, sortDirection)
                .TakePage(currentPage, pageSize)
                .AsEnumerable()
                .Select(CreateUser)
                .ToList();

            return users;
        }

        public int GetTotalUsers(Dictionary<UserListFilter, string> filterList)
        {
            return FilterUsers(filterList).Count();
        }

        public int EditPerson(Person person)
        {
            var entity = EntitiesContext.people.Where(p => p.id == person.Id).FirstOrDefault();
            entity.first_name = person.FirstName;
            entity.last_name = person.LastName;
            entity.email_address = person.EmailAddress;
            if(person.Avatar != null && person.Avatar.Length > 0) entity.avatar = person.Avatar;
            entity.gender = person.Gender;
            entity.language = person.Language;
            entity.updated_at = UniversalDate;
            entity.updated_by = person.UpdatedBy;

            EntitiesContext.SaveChanges();
            return entity.id;
        }

        public int AddPerson(Person person)
        {
            var entity = new people
                             {
                                 first_name = person.FirstName,
                                 last_name = person.LastName,
                                 email_address = person.EmailAddress,
                                 avatar = person.Avatar,
                                 gender = person.Gender,
                                 language = person.Language,
                                 created_at = UniversalDate,
                                 updated_at = UniversalDate,
                                 updated_by = person.UpdatedBy
                             };
            EntitiesContext.AddTopeople(entity);
            EntitiesContext.SaveChanges();
            return entity.id;
        }

        public int EditUser(User user)
        {
            var userEntity = EntitiesContext.users.Where(u => u.id == user.Id).FirstOrDefault();
            userEntity.activation_code = user.ActivationCode;
            userEntity.enabled = user.Enabled;
            userEntity.updated_at = UniversalDate;
            userEntity.updated_by = user.UpdatedBy;

            EntitiesContext.SaveChanges();

            return userEntity.id;
        }

        public int AddUser(User user)
        {
            var userEntity = new users
                                 {
                                     activation_code = user.ActivationCode,
                                     enabled = user.Enabled,
                                     password = string.Empty,
                                     salt = string.Empty,
                                     created_at = UniversalDate,
                                     updated_at = UniversalDate,
                                     updated_by = user.UpdatedBy,
                                     roles = EntitiesContext.roles.Where(r => r.id == user.Role.Id).FirstOrDefault(),
                                     people = EntitiesContext.people.Where(p => p.id == user.Person.Id).FirstOrDefault()
                                 };
            EntitiesContext.AddTousers(userEntity);
            EntitiesContext.SaveChanges();
            return userEntity.id;
        }

        public void UpdateLastAccess(string username)
        {
            var user = EntitiesContext.users.Where(u => u.people.email_address == username)
                .FirstOrDefault();
            user.last_access = UniversalDate;
            EntitiesContext.SaveChanges();
        }

        public void SavePassword(User user)
        {
            var userEntity = EntitiesContext.users.Where(u => u.id == user.Id).FirstOrDefault();
            userEntity.activation_code = user.ActivationCode;
            userEntity.password = user.Password;
            userEntity.salt = user.Salt;
            userEntity.updated_at = UniversalDate;

            EntitiesContext.SaveChanges();
        }

        #endregion

        #region PRIVATE METHODS

        private IQueryable<users> FilterUsers(Dictionary<UserListFilter, string> filters)
        {
            var users = EntitiesContext.users as IQueryable<users>;

            if (filters != null)
            {
                if (filters.Keys.Contains(UserListFilter.Id))
                {
                    int id;
                    if (int.TryParse(filters[UserListFilter.Id], out id))
                    {
                        return users.Where(item => item.id == id);
                    }
                }
                if (filters.Keys.Contains(UserListFilter.Name))
                {
                    var strName = filters[UserListFilter.Name];
                    users = users.Where(item => item.people.first_name.Contains(strName) || item.people.last_name.Contains(strName));
                }
                if (filters.Keys.Contains(UserListFilter.Email))
                {
                    var strEmail = filters[UserListFilter.Email];
                    users = users.Where(item => item.people.email_address.Contains(strEmail));
                }
                if (filters.Keys.Contains(UserListFilter.Role))
                {
                    var strRole = filters[UserListFilter.Role];
                    users = users.Where(item => item.roles.name.Contains(strRole));
                }
                if (filters.Keys.Contains(UserListFilter.Enabled))
                {
                    bool status;
                    if (bool.TryParse(filters[UserListFilter.Enabled], out status))
                    {
                        users = users.Where(item => item.enabled == status);
                    }
                }
            }

            return users;
        }

        private static IQueryable<users> SortUsers(IQueryable<users> query, UserListSortField sortField, SortDirectionType sortDirection)
        {
            switch (sortField)
            {
                case UserListSortField.Id:
                    return query.OrderBy(item => item.id, sortDirection);

                case UserListSortField.Name:
                    return query.OrderBy(item => item.people.first_name, sortDirection);

                case UserListSortField.Email:
                    return query.OrderBy(item => item.people.email_address, sortDirection);

                case UserListSortField.Role:
                    return query.OrderBy(item => item.roles.name, sortDirection);

                case UserListSortField.Enabled:
                    return query.OrderBy(item => item.enabled, sortDirection);

                case UserListSortField.CreatedAt:
                    return query.OrderBy(item => item.created_at, sortDirection);

                case UserListSortField.UpdatedAt:
                    return query.OrderBy(item => item.updated_at, sortDirection);

                case UserListSortField.LastAccess:
                    return query.OrderBy(item => item.last_access, sortDirection);

            }
            return query.OrderByDescending(item => item.id);
        }

        #endregion   
    }
}